package com.cuixichang.minimalism.support;

import com.cuixichang.minimalism.basal.cnstants.HttpHeader;
import com.cuixichang.minimalism.basal.utils.TimeUtils;
import com.cuixichang.minimalism.core.security.enums.RouterRelationTypePrefixEnum;
import com.cuixichang.minimalism.core.security.userdetails.CredentialDetail;
import com.cuixichang.minimalism.domain.IPermissionCommandService;
import com.cuixichang.minimalism.domain.IRoleCommandService;
import com.cuixichang.minimalism.service.ILoginService;
import com.cuixichang.minimalism.transfer.dto.ILoginDTO;
import com.cuixichang.minimalism.transfer.dto.IPermissionDTO;
import com.cuixichang.minimalism.transfer.dto.IRoleDTO;
import com.cuixichang.minimalism.transfer.po.ILogin;
import com.cuixichang.minimalism.transfer.po.IPermission;
import com.cuixichang.minimalism.transfer.po.IRole;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Component("userDetailsService")
public class AuthUserDetailsService implements UserDetailsService{
    @Autowired
    @Lazy
    private ILoginService iLoginService;
    @Autowired
    private IRoleCommandService iRoleCommandService;
    @Autowired
    private IPermissionCommandService iPermissionCommandService;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        String systemCode = request.getHeader(HttpHeader.SYSTEM_SOURCE_CODE);
        Optional.ofNullable(systemCode).orElseThrow(()->new BadCredentialsException("未获取到系统来源编码"));
        ILoginDTO iLogin = iLoginService.selectOne(ILoginDTO.builder().loginName(username).build());
        Optional.ofNullable(iLogin).orElseThrow(()->new UsernameNotFoundException("查询账号或密码异常,请检查"));
        List<IRoleDTO> iRoles = iRoleCommandService.loginHasBindingRoles(IRoleDTO.builder().isEnable(true).build(),systemCode,iLogin.getId(),iLogin.getId());
        Optional.of(iRoles).filter(list->!list.isEmpty()).orElseThrow(()->new BadCredentialsException("账号未分配角色,请检查"));
        String rolePrefix = RouterRelationTypePrefixEnum.Role.getPrefix();
        List<String> roleAuths = iRoles.stream().map(IRoleDTO::getRoleCode).map(rolePrefix::concat).collect(Collectors.toList());
        List<Long> roleIds = iRoles.stream().map(IRoleDTO::getId).collect(Collectors.toList());
        List<IPermissionDTO> iPermissions = iPermissionCommandService.rolesHasBindingPermissions(IPermissionDTO.builder().isEnable(true).build(),systemCode,roleIds);
        List<String> permissionAuths = Collections.EMPTY_LIST;
        if(!CollectionUtils.isEmpty(iPermissions)){
            String permissionPrefix = RouterRelationTypePrefixEnum.Permission.getPrefix();
            permissionAuths = iPermissions.stream().map(IPermissionDTO::getPermissionCode).map(permissionPrefix::concat).collect(Collectors.toList());

        }
        return CredentialDetail.builder().username(username).password(iLogin.getLoginPassword())
                .enabled(iLogin.getIsEnable())
                .accountNonExpired(Objects.isNull(iLogin.getLogoffTime()) ?null:TimeUtils.toMilliSecond(iLogin.getLogoffTime()))
                .credentialsNonExpired(Objects.isNull(iLogin.getReAuthTime()) ?null:TimeUtils.toMilliSecond(iLogin.getReAuthTime()))
                .accountNonLocked(!iLogin.getIsLock())
                .systemCode(systemCode).loginId(iLogin.getId()).groupId(iLogin.getGroupId())
                .authorities(Stream.concat(roleAuths.stream(),permissionAuths.stream()).collect(Collectors.toList())).build();
    }
}
